package com.example.demo01.config;

import com.example.demo01.component.MyErrorAttributes;
import com.example.demo01.component.MyLocaleResolver;
import com.example.demo01.filter.HelloFilter;
import com.example.demo01.interceptor.EachMethodTakesTimeInterceptor;
import com.example.demo01.listener.MyServletContextListener;
import com.example.demo01.servlet.HelloServlet;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * 调用顺序: Filter --> Interceptor --> Aop --> Handler
 */
@Configuration
//@EnableWebMvc
public class ApplicationConfig implements WebMvcConfigurer {

    private final ServerProperties serverProperties;

    public ApplicationConfig(ServerProperties serverProperties) {
        this.serverProperties = serverProperties;
    }

    /**
     * 注册一个 Servlet
     *
     * @see HelloServlet
     */
    @Bean
    public ServletRegistrationBean<HelloServlet> helloServlet() {
        ServletRegistrationBean<HelloServlet> helloServlet = new ServletRegistrationBean<>(new HelloServlet(), "/servlet");
        helloServlet.setLoadOnStartup(2);
        return helloServlet;
    }


    /**
     * 注册一个 Filter
     *
     * @see HelloFilter
     */
    @Bean
    public FilterRegistrationBean<HelloFilter> helloFilter() {
        FilterRegistrationBean<HelloFilter> helloFilter = new FilterRegistrationBean<>();
        helloFilter.setFilter(new HelloFilter());
        helloFilter.addUrlPatterns("/hello", "/servlet");
        return helloFilter;
    }

    /**
     * 注册一个监听器
     */
    @Bean
    public ServletListenerRegistrationBean<MyServletContextListener> myServletContextListener() {
        return new ServletListenerRegistrationBean<>(new MyServletContextListener());
    }


    /**
     * 注册拦截器: 与 Spring.xml 配置文件中的 <mvc:interceptors> 相对应
     * 1. 实现 WebMvcConfigurer
     * 2. 重写 addInterceptors
     * @see EachMethodTakesTimeInterceptor
     */
//    @Override
//    public void addInterceptors(InterceptorRegistry registry) {
//        registry.addInterceptor(new EachMethodTakesTimeInterceptor()).
//                addPathPatterns("/**").
//                excludePathPatterns("/", "/index.html");

//        registry.addInterceptor(new LoginHandlerInterceptor()).
//                addPathPatterns("/**").
//                excludePathPatterns("/", "/index.html", "/login.html", "/user/login");
//    }


    /**
     * 注册视图控制器: 与 Spring.xml 配置文件中的 <mvc:view-controller path="" view-name=""/> 相对应
     * 1. 实现 WebMvcConfigurer
     * 2. 重写 addViewControllers
     * 如果请求中不需要数据数据填充，那么没必要将请求与 Controller 映射，直接写到这里
     */
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/viewController01").setViewName("success");
        registry.addViewController("/viewController02").setViewName("success");
    }


    /**
     * 错误页面的处理:
     * 1.模板引擎的精准匹配，静态资源的精准匹配；
     * 2.模板引擎的模糊匹配，静态资源的模糊匹配。
     */


    /**
     * webjars
     * @EnableWebMvc
     * --> 导入 DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport
     * --> 而 WebMvcAutoConfiguration 上有注解: @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
     * 当容器中没有 WebMvcConfigurationSupport 类型的组件，WebMvcAutoConfiguration 此配置才会生效。
     * 而如果在配置类上标注 @EnableWebMvc，那么容器中就会导入 WebMvcConfigurationSupport，那么 WebMvcAutoConfiguration 失效。
     */


    /**
     * SpringBoot 的优点: 零配置、不需要特意去整合、不需要考虑 Maven 的依赖。
     * SpringBoot 的缺点: 启动的时候组件比较多，启动速度慢，内存消耗比较多，入门容易、精通难。
     */


    @Bean
    public WebMvcConfigurer webMvcConfigurer() {
        WebMvcConfigurer webMvcConfigurer = new WebMvcConfigurer() {
            @Override
            public void addViewControllers(ViewControllerRegistry registry) {
                registry.addViewController("/").setViewName("login");
                registry.addViewController("/login.html").setViewName("login");
                registry.addViewController("/main.html").setViewName("dashboard");
            }
        };
        return webMvcConfigurer;
    }

//    @Bean
//    public LocaleResolver localeResolver() {
//        return new MyLocaleResolver();
//    }

    @Bean
    public DefaultErrorAttributes myErrorAttributes() {
        return new MyErrorAttributes(this.serverProperties.getError().isIncludeException());
    }
}
